<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="coinfaces">

        <title>JavaScript里this绑定</title>

    <link rel="stylesheet" href="../../theme/css/style.css">
    <link rel="stylesheet" href="../../theme/css/pygments.css">



</head>

<body>
    <div class="content">
<h1>JavaScript里this绑定</h1>    <p>
        under
            <a href="../../tags/javascript/">javascript</a>
    </p>
    <p>
        in <a href="../../categories/tech/">tech</a>
    </p>
    <p>Published: 2016-08-08</p>


    <p>我看过的介绍JavaScript里<tt class="docutils literal">this</tt>用法最清晰的文章是<a class="reference external" href="http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html">阮一峰的Javascript的this用法</a>，简单列举一下里面介绍的4种用法：</p>
<ul class="simple">
<li>绑定构造中（<tt class="docutils literal">new</tt>）的对象：<tt class="docutils literal">var o = new (function () { this.x = 1; <span class="pre">})();</span></tt></li>
<li>绑定全局对象：<tt class="docutils literal">(function () { this.x = 1; <span class="pre">})();</span></tt></li>
<li>绑定调用方法的对象：<tt class="docutils literal">var o = { f : function () { this.x = 1; } }; <span class="pre">o.f();</span></tt></li>
<li><tt class="docutils literal">apply</tt>或<tt class="docutils literal">call</tt>显示绑定：<tt class="docutils literal">var m = {}; (function () { this.x = 1; <span class="pre">}).apply(m);</span></tt></li>
</ul>
<p>对这4种方法都验证了一下，觉得自己懂了，但后来发现自己对<tt class="docutils literal">apply</tt>原理的理解是不够的，只看到函数的<tt class="docutils literal">this</tt>绑定了<tt class="docutils literal">apply</tt>的第一个参数,却没有意识到<tt class="docutils literal">apply</tt>的<tt class="docutils literal">this</tt>绑定了函数对象，以至于后来查<tt class="docutils literal">Array.prototype.slice</tt>用法时看到一个技巧，一下子没能理解。</p>
<p><tt class="docutils literal">Array.prototype.slice</tt>可被用来将类似于<tt class="docutils literal">Array</tt>的对象转化成<tt class="docutils literal">Array</tt>：</p>
<div class="highlight"><pre><span></span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">[].</span><span class="nx">slice</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">arguments</span><span class="p">);</span>
<span class="p">})(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span> <span class="c1">// [1, 2, 3]</span>
</pre></div>
<p>有人不想经常写这么长的语句，就用<tt class="docutils literal">Function.prototype.bind</tt>制造了一个不借助<tt class="docutils literal">apply</tt>就可以直接使用的<tt class="docutils literal">slice</tt>函数：</p>
<div class="highlight"><pre><span></span><span class="kd">var</span> <span class="nx">slice</span> <span class="o">=</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">call</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">slice</span><span class="p">);</span>
</pre></div>
<p>这下用起来方便多了：</p>
<div class="highlight"><pre><span></span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">slice</span><span class="p">(</span><span class="nx">arguments</span><span class="p">);</span>
<span class="p">})(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span> <span class="c1">// [1, 2, 3]</span>
</pre></div>
<p>这个技巧就是借用了函数对象调用<tt class="docutils literal">apply</tt>或<tt class="docutils literal">call</tt>的时候，其本身就被绑定为<tt class="docutils literal">apply</tt>或<tt class="docutils literal">call</tt>的<tt class="docutils literal">this</tt>，用<tt class="docutils literal">bind</tt>将<tt class="docutils literal">Array.prototype.slice</tt>绑定为<tt class="docutils literal">call</tt>的<tt class="docutils literal">this</tt>后，其实相当于写了<tt class="docutils literal">Array.prototype.slice.call</tt>这一部分。另一个细节是用<tt class="docutils literal">call</tt>而非<tt class="docutils literal">apply</tt>进行绑定，这可以让新<tt class="docutils literal">slice</tt>的使用方式更接近<tt class="docutils literal">Array.prototype.slice</tt>，否则<tt class="docutils literal"><span class="pre">slice([1,</span> 2, 3], 1)</tt>就必须被写成<tt class="docutils literal"><span class="pre">slice([1,</span> 2, 3], [1])</tt>。</p>
<p>（完）</p>

    </div>
<nav class="nav sidebar">
    <div class="siteinfo">
        <div class="sitename"><a href="../..">coinfaces</a></div>
        <div class="tagline">Another Side of Life</div>
    </div>

        <a href="../../categories/">categories</a>
        <a href="../..">&larr; Home</a>
</nav><footer class="footer">
    <span>
        &copy; jpli &middot;
        under <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA 4.0</a>
    </span>
    |
    <span>
        Powered by:
        <a href="http://blog.getpelican.com/">Pelican</a>
    </span>
</footer></body>
</html>